// Favicon 缓存管理工具 - 重构版本
// 架构：Background抓取 + ArrayBuffer存储 + LRU管理 + 消息通信

import type {FaviconCache, FaviconLRUConfig, FaviconMessage, FaviconResponse} from '@/types';
import {chromeStorage} from '@/lib/chromeStorage';
import {getFaviconCacheKey} from '@/lib/storageKeys';
import {getDefaultFaviconSvg} from '@/lib/utils';
import {chromeRuntime} from '@/lib/chromeApi';

// LRU缓存配置
const LRU_CONFIG: FaviconLRUConfig = {
    // 最大缓存条目数
    maxEntries: 300,
    // 最大总字节数（9MB，预留chrome.storage配额）
    maxTotalBytes: 6 * 1024 * 1024,
    // 清理触发阈值（达到90%时开始清理）
    cleanupThreshold: 0.8
};

// Favicon 缓存相关常量
const FAVICON_CACHE_TTL = 7 * 24 * 60 * 60 * 1000; // 7天过期时间

/**
 * 提取域名的工具函数（区分子域名和主域名）
 */
function getDomain(url: string): string {
    try {
        return new URL(url).hostname;
    } catch {
        return url;
    }
}

/**
 * 检查缓存是否有效（未过期）
 */
function isCacheValid(cache: FaviconCache): boolean {
    const now = Date.now();
    return (now - cache.timestamp) < FAVICON_CACHE_TTL;
}

/**
 * 将ArrayBuffer转换为DataURL
 */
function arrayBufferToDataURL(buffer: ArrayBuffer, mimeType: string): string {
    const bytes = new Uint8Array(buffer);
    const binary = Array.from(bytes, byte => String.fromCharCode(byte)).join('');
    const base64 = btoa(binary);
    return `data:${mimeType};base64,${base64}`;
}

/**
 * 从缓存加载图标
 * @param url 页面URL
 * @returns Promise<string | null> 缓存的DataURL或null
 */
export async function loadFaviconFromCache(url: string): Promise<string | null> {
    try {
        const domain = getDomain(url);
        const cacheKey = getFaviconCacheKey(domain);
        const cache = await chromeStorage.load<FaviconCache>(cacheKey);

        if (cache && isCacheValid(cache)) {
            return cache.dataUrl;
        }
    } catch (error) {
        console.warn(`加载 ${url} 的favicon缓存失败:`, error);
    }
    return null;
}

/**
 * 保存favicon到缓存（ArrayBuffer版本）
 * @param url 页面URL
 * @param data 二进制图像数据
 * @param mimeType MIME类型
 * @param source 图标来源
 */
export async function saveFaviconToCache(
    url: string,
    data: ArrayBuffer,
    mimeType: string,
    source: FaviconCache['source']
): Promise<void> {
    try {
        const domain = getDomain(url);
        const cacheKey = getFaviconCacheKey(domain);

        // 将ArrayBuffer直接转换为完整DataURL
        const dataUrl = arrayBufferToDataURL(data, mimeType);

        // 构建缓存对象
        const cache: FaviconCache = {
            dataUrl,
            timestamp: Date.now(),
            source,
            byteSize: data.byteLength,
            expires: Date.now() + FAVICON_CACHE_TTL
        };

        // 轻量级清理检查，避免阻塞保存操作
        if (shouldTriggerCleanup(data.byteLength)) {
            performLRUCleanupIfNeeded(data.byteLength).catch(error => {
                console.error('异步LRU清理失败:', error);
            });
        }

        // 保存到Chrome存储
        await chromeStorage.save(cacheKey, cache);
        console.debug(`保存favicon缓存成功: ${domain}, ${data.byteLength}字节, ${source}`);
    } catch (error) {
        console.warn(`保存 ${url} 的favicon缓存失败:`, error);
    }
}

// LRU清理节流：5分钟内只能触发一次
let lastLRUCleanupTime = 0;
const LRU_CLEANUP_THROTTLE_MS = 5 * 60 * 1000; // 5分钟

/**
 * LRU清理节流检查（防止频繁触发灾难性全量存储读取）
 *
 * 设计原则：
 * - LRU清理是重量级操作（全量读取Chrome Storage），必须严格节流
 * - 5分钟内只允许触发一次，避免大量tab场景下的性能灾难
 * - 宁可容忍轻微的存储浪费，也不能让用户体验崩溃
 */
function shouldTriggerCleanup(_newDataSize: number): boolean {
    const now = Date.now();

    // 时间窗口保护：5分钟内禁止重复触发
    if (now - lastLRUCleanupTime < LRU_CLEANUP_THROTTLE_MS) {
        return false;
    }

    // 10%概率触发，但受时间窗口保护
    const shouldTrigger = Math.random() < 0.1;
    if (shouldTrigger) {
        lastLRUCleanupTime = now;
        console.debug('LRU清理节流触发，下次最早触发时间：', new Date(now + LRU_CLEANUP_THROTTLE_MS));
    }

    return shouldTrigger;
}

/**
 * 执行LRU清理（如果需要）
 * 使用异步执行避免阻塞UI线程
 */
async function performLRUCleanupIfNeeded(newDataSize: number): Promise<void> {
    try {
        // 性能优化：一次性获取所有数据，避免getAllKeys + loadBulk的双重读取
        const allData = await chromeStorage.getAllData();
        const faviconEntries = Object.entries(allData).filter(([key]) => key.startsWith('fc-'));

        if (faviconEntries.length === 0) return;
        const cacheEntries: Array<{ key: string; cache: FaviconCache }> = [];
        let totalBytes = 0;

        // 统计当前缓存状态（数据已在内存中，无需重复加载）
        for (const [key, cache] of faviconEntries) {
            if (cache && typeof cache === 'object' && 'dataUrl' in cache) {
                const faviconCache = cache as FaviconCache;
                cacheEntries.push({key, cache: faviconCache});
                totalBytes += faviconCache.byteSize;
            }
        }

        // 检查是否需要清理
        const wouldExceedLimit = (totalBytes + newDataSize) > (LRU_CONFIG.maxTotalBytes * LRU_CONFIG.cleanupThreshold);
        const tooManyEntries = cacheEntries.length >= LRU_CONFIG.maxEntries;

        if (!wouldExceedLimit && !tooManyEntries) return;

        console.debug('触发LRU清理:', {
            currentEntries: cacheEntries.length,
            currentBytes: totalBytes,
            newDataSize,
            maxEntries: LRU_CONFIG.maxEntries,
            maxBytes: LRU_CONFIG.maxTotalBytes
        });

        // 按时间戳排序（最旧的在前）
        cacheEntries.sort((a, b) => a.cache.timestamp - b.cache.timestamp);

        // 清理策略：删除最旧的缓存直到满足条件
        const keysToDelete: string[] = [];
        let bytesToRemove = 0;

        for (const {key, cache} of cacheEntries) {
            keysToDelete.push(key);
            bytesToRemove += cache.byteSize;

            // 检查清理后是否满足条件
            const remainingEntries = cacheEntries.length - keysToDelete.length;
            const remainingBytes = totalBytes - bytesToRemove;

            if (remainingEntries < LRU_CONFIG.maxEntries &&
                (remainingBytes + newDataSize) < (LRU_CONFIG.maxTotalBytes * LRU_CONFIG.cleanupThreshold)) {
                break;
            }
        }

        // 批量删除
        if (keysToDelete.length > 0) {
            await chromeStorage.deleteBulk(keysToDelete);
            console.debug(`LRU清理完成: 删除${keysToDelete.length}个缓存, 释放${bytesToRemove}字节`);
        }
    } catch (error) {
        console.error('LRU清理失败:', error);
    }
}

/**
 * 根据URL加载favicon（新架构：通过Background抓取）
 * @param url 页面URL
 * @param savedFavicon 保存的favicon URL（可选）
 * @returns Promise<string> favicon的DataURL
 */
export async function loadFaviconWithCache(url: string, savedFavicon?: string): Promise<string> {
    try {
        // 第一步：尝试从本地缓存加载
        const cachedDataUrl = await loadFaviconFromCache(url);
        if (cachedDataUrl) {
            return cachedDataUrl;
        }

        // 第二步：缓存未命中，通过Background Service Worker抓取
        const message: FaviconMessage = {
            type: 'FETCH_FAVICON',
            data: {url, savedFavicon}
        };

        // 使用chromeApi统一管理Chrome相关调用
        const response = await chromeRuntime.sendMessage(message) as FaviconResponse;

        if (response.success && response.result) {
            return response.result.dataUrl;
        } else {
            throw new Error(response.error || 'Background抓取失败');
        }

    } catch (error) {
        console.warn(`加载 ${getDomain(url)} 的favicon失败:`, error);
        // 返回默认SVG fallback
        return getDefaultFaviconSvg();
    }
}

/**
 * 清理过期的favicon缓存
 */
export async function cleanupExpiredFaviconCache(): Promise<void> {
    try {
        const allData = await chromeStorage.getAllData();
        const faviconEntries = Object.entries(allData).filter(([key]) => key.startsWith('fc-'));

        if (faviconEntries.length === 0) return;

        const expiredKeys: string[] = [];

        for (const [key, cache] of faviconEntries) {
            if (cache && typeof cache === 'object' && 'timestamp' in cache) {
                const faviconCache = cache as FaviconCache;
                if (!isCacheValid(faviconCache)) {
                    expiredKeys.push(key);
                }
            }
        }

        if (expiredKeys.length > 0) {
            await chromeStorage.deleteBulk(expiredKeys);
            console.debug(`清理过期favicon缓存: 删除${expiredKeys.length}个过期缓存`);
        }
    } catch (error) {
        console.error('清理过期缓存失败:', error);
    }
}

/**
 * 获取favicon缓存统计信息
 */
export async function getFaviconCacheStats(): Promise<{
    totalEntries: number;
    totalBytes: number;
    oldestEntry: number;
    newestEntry: number;
}> {
    try {
        // 性能优化：一次性获取所有数据，避免getAllKeys + loadBulk的双重读取
        const allData = await chromeStorage.getAllData();
        const faviconEntries = Object.entries(allData).filter(([key]) => key.startsWith('fc-'));

        if (faviconEntries.length === 0) {
            return {totalEntries: 0, totalBytes: 0, oldestEntry: 0, newestEntry: 0};
        }
        let totalBytes = 0;
        let oldestEntry = Date.now();
        let newestEntry = 0;

        for (const [, cache] of faviconEntries) {
            if (cache && typeof cache === 'object' && 'byteSize' in cache && 'timestamp' in cache) {
                const faviconCache = cache as FaviconCache;
                totalBytes += faviconCache.byteSize;
                oldestEntry = Math.min(oldestEntry, faviconCache.timestamp);
                newestEntry = Math.max(newestEntry, faviconCache.timestamp);
            }
        }

        return {
            totalEntries: faviconEntries.length,
            totalBytes,
            oldestEntry,
            newestEntry
        };
    } catch (error) {
        console.error('获取缓存统计失败:', error);
        return {totalEntries: 0, totalBytes: 0, oldestEntry: 0, newestEntry: 0};
    }
}
